<template>
	<div ref="messageContainer" class="h-100% overflow-y-auto relative">
		<div class="chat-list" v-for="(item, index) in list" :key="index">
			<div class="left-message message-item" v-if="+item?.type !== 2">
				<div class="avatar">
					<el-avatar :src="roleAvatar"/>
				</div>
				<div class="message">
					<div class="left-text-container" ref="markdownViewRef" v-if="item?.content">
						<MarkdownView class="left-text" :content="item?.content"/>
					</div>
					
					<div>
						<el-text class="time">{{ formatDate(item?.createTime) }}</el-text>
					</div>
					<div class="left-btns">
						<el-button class="btn-cus" link @click="copyContent(item?.content)">
							<img class="btn-image" src="@/assets/ai/copy.svg"/>
						</el-button>
						<el-button class="btn-cus" link>
							<el-popover
									placement="bottom-start"
									:width="584"
									trigger="click"
									ref="popoverRef"
									:offset="18"
									:show-arrow="false">
								<template #reference>
									<img class="btn-image h-17px" src="@/assets/ai/feedback.svg"/>
								</template>
								<div class="fb_box">
									<div class="fb_box_title">
										请与我们分享更多信息：
										<img src="@/assets/ai/close.png" @click="hidePopover"/>
									</div>
									<div class="flex align-center fb_box_content">
										<div
												class="fb_box_content_item"
												v-for="(name,index) in fbList"
												:key="index"
												@click="createFb(name,item)">{{ name }}
										</div>
										<el-input v-model="fbValue" placeholder="更多反馈原因"/>
										<div class="fb_box_content_confirm" @click="createFb(fbValue,item)">提交</div>
									</div>
								</div>
							</el-popover>
						</el-button>
					</div>
				</div>
			</div>
			<!-- 靠右 message：user 类型 -->
			<div class="right-message message-item" v-if="+item?.type === 2">
				<div class="avatar">
					<el-avatar :src="userAvatar"/>
				</div>
				<div class="message">
					<div class="right-text-container">
						<div class="right-text" v-if="item.voiceUrl">
							<audio controls>
								<source :src="item.voiceUrl"/>
							</audio>
						</div>
						<div class="right-text" v-else>{{ item?.content }}</div>
					</div>
					<div>
						<el-text class="time" style="text-align: right">{{ formatDate(item?.createTime) }}</el-text>
					</div>
					<div class="files">
						<div class="files-item" v-for="(file,fileIndex) in item?.file" :key="fileIndex">
							<div class="files-item-name">{{ file.fileName }}</div>
							<div class="files-item-down" @click="downFile(file)">
								<img src="@/assets/ai/down.png"/>
								<text style="white-space: nowrap">下载</text>
							</div>
						</div>
						<!-- <div class="voice-item" v-if="item.voiceUrl">
              <div class="voice-item-name">
                <audio controls>
                  <source :src="item.voiceUrl"/>
                </audio>
              </div>
            </div> -->
					</div>
					<!--          <div class="right-btns">-->
					<!--            <el-button class="btn-cus" link @click="copyContent(item.content)">-->
					<!--              <img class="btn-image" src="@/assets/ai/copy.svg" />-->
					<!--            </el-button>-->
					<!--            <el-button class="btn-cus" link @click="onDelete(item.id)">-->
					<!--              <img class="btn-image h-17px mr-12px" src="@/assets/ai/delete.svg" />-->
					<!--            </el-button>-->
					<!--            <el-button class="btn-cus" link @click="onRefresh(item)">-->
					<!--              <el-icon size="17"><RefreshRight /></el-icon>-->
					<!--            </el-button>-->
					<!--            <el-button class="btn-cus" link @click="onEdit(item)">-->
					<!--              <el-icon size="17"><Edit /></el-icon>-->
					<!--            </el-button>-->
					<!--          </div>-->
				</div>
			</div>
		</div>
	</div>
	<!-- 回到底部 -->
	<div v-if="isScrolling" class="to-bottom" @click="handleGoBottom">
		<el-button :icon="ArrowDownBold" circle/>
	</div>
</template>
<script setup lang="ts">
import {PropType} from 'vue'
import {formatDate} from '@/utils/formatTime'
import MarkdownView from '@/components/MarkdownView/index.vue'
import {useClipboard} from '@vueuse/core'
import {ArrowDownBold, Edit, RefreshRight} from '@element-plus/icons-vue'
import {ChatMessageApi, ChatMessageVO} from '@/api/ai/chat/message'
import {ChatConversationVO} from '@/api/ai/chat/conversation'
import {useUserStore} from '@/store/modules/user'
import userAvatarDefaultImg from '@/assets/imgs/avatar.gif'
import roleAvatarDefaultImg from '@/assets/ai/gpt.svg'
import consola from "consola";
import {windows} from "rimraf";

const message = useMessage() // 消息弹窗
const {copy} = useClipboard() // 初始化 copy 到粘贴板
const userStore = useUserStore()

// 判断“消息列表”滚动的位置(用于判断是否需要滚动到消息最下方)
const messageContainer: any = ref(null)
const isScrolling = ref(false) //用于判断用户是否在滚动

const userAvatar = computed(() => userStore.user.avatar ?? userAvatarDefaultImg)
const roleAvatar = computed(() => props.conversation.roleAvatar ?? roleAvatarDefaultImg)
/**
 * 下载文件
 * @param file
 */
const downFile = (file) => {
  const link = document.createElement('a');
  link.style.display = 'none';
  // 设置下载地址
  link.setAttribute('href', file.fileUrl);
  // 设置文件名
  link.setAttribute('download', file.fileName);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  
}

// 定义 props
const props = defineProps({
  conversation: {
    type: Object as PropType<ChatConversationVO>,
    required: true
  },
  list: {
    type: Array as PropType<ChatMessageVO[]>,
    required: true
  }
})

const popoverRef = ref(null)
const fbValue = ref('');
const fbList = [
  '与事实不符',
  '未完全遵循指令',
  '不喜欢这种风格',
  '不是很详细',
  '内容错误',
  '更多...',
]

const hidePopover = () => {
  popoverRef.value.some(item => item.hide())
  fbValue.value = ''
}

const createFb = (content, item) => {
  if (content === '更多...') return;
  
  ChatMessageApi.updateComment({
    id: item.id,
    feedback: content
  }).then(() => {
    hidePopover()
    message.success('反馈成功！')
  })
}

const {list} = toRefs(props) // 消息列表

const emits = defineEmits(['onDeleteSuccess', 'onRefresh', 'onEdit']) // 定义 emits

// ============ 处理对话滚动 ==============

/** 滚动到底部 */
const scrollToBottom = async (isIgnore?: boolean) => {
  // 注意要使用 nextTick 以免获取不到 dom
  await nextTick()
  if (isIgnore || !isScrolling.value) {
    messageContainer.value.scrollTop =
        messageContainer.value.scrollHeight - messageContainer.value.offsetHeight
  }
}

function handleScroll() {
  const scrollContainer = messageContainer.value
  const scrollTop = scrollContainer.scrollTop
  const scrollHeight = scrollContainer.scrollHeight
  const offsetHeight = scrollContainer.offsetHeight
  if (scrollTop + offsetHeight < scrollHeight - 100) {
    // 用户开始滚动并在最底部之上，取消保持在最底部的效果
    isScrolling.value = true
  } else {
    // 用户停止滚动并滚动到最底部，开启保持到最底部的效果
    isScrolling.value = false
  }
}

/** 回到底部 */
const handleGoBottom = async () => {
  const scrollContainer = messageContainer.value
  scrollContainer.scrollTop = scrollContainer.scrollHeight
}

/** 回到顶部 */
const handlerGoTop = async () => {
  const scrollContainer = messageContainer.value
  scrollContainer.scrollTop = 0
}

defineExpose({scrollToBottom, handlerGoTop}) // 提供方法给 parent 调用

// ============ 处理消息操作 ==============

/** 复制 */
const copyContent = async (content) => {
  await copy(content)
  message.success('复制成功！')
}

/** 删除 */
const onDelete = async (id) => {
  // 删除 message
  await ChatMessageApi.deleteChatMessage(id)
  message.success('删除成功！')
  // 回调
  emits('onDeleteSuccess')
}

/** 刷新 */
const onRefresh = async (message: ChatMessageVO) => {
  emits('onRefresh', message)
}

/** 编辑 */
const onEdit = async (message: ChatMessageVO) => {
  emits('onEdit', message)
}

/** 初始化 */
onMounted(async () => {
  messageContainer.value.addEventListener('scroll', handleScroll)
})
</script>

<style scoped lang="scss">

.voice {
  &-item {
    background: #F4F4F4;
    border-radius: 8px 8px 8px 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 338px;
    box-sizing: border-box;
    background: #F4F4F4;
    border-radius: 8px 8px 8px 8px;
    margin-top: 12px;
    
    &-name {
      font-weight: 400;
      font-size: 14px;
      color: #0D0D0D;
    }
    
    &-down {
      cursor: pointer;
      display: flex;
      align-items: center;
      
      img {
        $wh: 20px;
        width: $wh;
        height: $wh;
        margin-right: 2px;
      }
      
      font-weight: 400;
      font-size: 14px;
      color: #9B9B9B;
    }
  }
}

.files {
  &-item {
    background: #F4F4F4;
    border-radius: 8px 8px 8px 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 338px;
    padding: 14px 16px;
    box-sizing: border-box;
    background: #F4F4F4;
    border-radius: 8px 8px 8px 8px;
    margin-top: 12px;
    
    &-name {
      font-weight: 400;
      font-size: 14px;
      color: #0D0D0D;
    }
    
    &-down {
      cursor: pointer;
      display: flex;
      align-items: center;
      
      img {
        $wh: 20px;
        width: $wh;
        height: $wh;
        margin-right: 2px;
      }
      
      font-weight: 400;
      font-size: 14px;
      color: #9B9B9B;
    }
  }
}

.fb_box {
  &_content {
    flex-wrap: wrap;
    
    &_item {
      cursor: pointer;
      margin-top: 12px;
      margin-right: 12px;
      white-space: nowrap;
      height: 30px;
      line-height: 30px;
      background: #FFFFFF;
      border-radius: 8px 8px 8px 8px;
      border: 1px solid #EEEEEE;
      padding: 0 12px;
      
      font-weight: 400;
      font-size: 14px;
      color: #9B9B9B;
    }
    
    &_confirm {
      width: 64px;
      height: 30px;
      line-height: 30px;
      text-align: center;
      background: #0D0D0D;
      border-radius: 8px 8px 8px 8px;
      font-weight: 400;
      font-size: 14px;
      color: #FFFFFF;
      margin-top: 12px;
      margin-left: 20px;
      cursor: pointer;
    }
    
    :deep(.el-input) {
      opacity: .9;
      margin-top: 12px;
      width: 205px;
      height: 30px;
      background: #FFFFFF;
      border-radius: 8px 8px 8px 8px;
      outline: none;
    }
  }
  
  &_title {
    font-weight: 400;
    font-size: 14px;
    color: #999999;
    position: relative;
    
    img {
      position: absolute;
      right: 0;
      width: 14px;
      height: 14px;
      cursor: pointer;
    }
  }
}

.message-container {
  position: relative;
  overflow-y: scroll;
}

// 中间
.chat-list {
  display: flex;
  flex-direction: column;
  overflow-y: hidden;
  padding: 0 20px;
  
  .message-item {
    margin-top: 50px;
  }
  
  .left-message {
    display: flex;
    flex-direction: row;
  }
  
  .right-message {
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-start;
  }
  
  .message {
    display: flex;
    flex-direction: column;
    text-align: left;
    margin: 0 15px;
    
    .time {
	    
      line-height: 30px;
      margin-top: 8px;
      display: block;
      font-weight: 400;
      font-size: 14px;
      color: #999999;
    }
    
    .left-text-container {
      position: relative;
      display: flex;
      flex-direction: column;
      overflow-wrap: break-word;
      border-radius: 10px;
      
      font-weight: 500;
      font-size: 16px;
      color: #0D0D0D;
      
      .left-text {
        color: #393939;
        font-size: 0.95rem;
      }
    }
    
    .right-text-container {
      display: flex;
      flex-direction: row-reverse;
      
      .right-text {
        font-size: 0.95rem;
        color: #fff;
        display: inline;
        width: auto;
        overflow-wrap: break-word;
        white-space: pre-wrap;
        font-weight: 500;
        font-size: 16px;
        color: #0D0D0D;
      }
    }
    
    .left-btns {
      display: flex;
      flex-direction: row;
      margin-top: 8px;
    }
    
    .right-btns {
      display: flex;
      flex-direction: row-reverse;
      margin-top: 8px;
    }
  }
  
  // 复制、删除按钮
  .btn-cus {
    display: flex;
    background-color: transparent;
    align-items: center;
    
    .btn-image {
      height: 20px;
    }
  }
  
  .btn-cus:hover {
    cursor: pointer;
    background-color: #f6f6f6;
  }
}

// 回到底部
.to-bottom {
  position: absolute;
  z-index: 1000;
  bottom: 0;
  right: 50%;
}
</style>
